#ifndef _PROCESS_POLL_HPP__
#define _PROCESS_POLL_HPP__

#include <iostream>
#include <vector>
#include <unistd.h>
#include<cstdlib>
#include<string>
#include<sys/wait.h>
#include"Task.hpp"


class Channel
{
private:
    int _wfd;
    pid_t _subid;
    std::string _name;

public:
    Channel(int wfd, pid_t subid)
        : _wfd(wfd), _subid(subid)
    {
        _name="channel-"+std::to_string(_wfd)+"-"+std::to_string(_subid);
    }
    ~Channel()
    {
    }

    std::string GetName()
    {
        return _name;
    }

    void Send(int code)
    {
        int n=write(_wfd,&code,sizeof(int));
        (void)n;
    }
    void Close()
    {
        close(_wfd);
    }

    void Wait()
    {
        int ret=waitpid(_subid,nullptr,0);
        (void)ret;
    }
};

class ChannelManager
{
private:
    std::vector<Channel> _channels;
    int _next;
public:
    ChannelManager():_next(0)
    {
    }

    ~ChannelManager()
    {
    }


    Channel& Select()
    {
        auto & c=_channels[_next];
        _next++;
        _next%=_channels.size();
        return c;
    }

    void Insert(int wfd, pid_t pid)
    {
        _channels.emplace_back(wfd, pid);
    }

    void PrintChannel()
    {
        for(auto x:_channels)
        {
            std::cout<<x.GetName()<<std::endl;
        }
    }

    void CloseChannel()
    {
        for(auto& x:_channels)
        {
            x.Close();
            std::cout<<"关闭:"<<x.GetName()<<std::endl;
        }
    }

    void StopChannel()
    {
        for(auto& x:_channels)
        {
            x.Wait();
            std::cout<<"回收:"<<x.GetName()<<std::endl;
        }
    }
};

const int gddefaultnum = 5;



class ProcessPool
{
private:
    ChannelManager _cm;
    int _process_num;
    TaskManager _tm;
    

public:
    ProcessPool(int num)
        : _process_num(num)
    {
        _tm.Register(Upload);
        _tm.Register(DownLoad);
        _tm.Register(PrintLog);
    }


    void work(int pipefd)
    {
        while(1)
        {

            int code=0;
            ssize_t n=read(pipefd,&code,sizeof(int));
            if(n>0)
            {
                if(n!=sizeof(int))
                {
                    continue;
                }
                std::cout<<"子进程["<<getpid()<<"]收到一个任务码"<<code<<std::endl;
                _tm.Execute(code);
            }
            else if(n==0)
            {
                std::cout<<"子进程退出"<<std::endl;
                break;
            }
            else{
                std::cout<<"读取错误"<<std::endl;
                break;

            }


            // std::cout<<"我是子进程,我的pid:"<<getpid()<<"文件描述符:"<<pipefd<<std::endl;
            // sleep(1);
        }

    }

    void Debug()
    {
       _cm.PrintChannel();

    }

    bool start()
    {
        for (int i = 0; i < _process_num; i++)
        {
            // 1.创建管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                std::cerr << "创建管道失败" << std::endl;
                return false;
            }

            // 创建子进程
            pid_t subid = fork();
            if (subid < 0)
                return false;
            else if (subid == 0)
            {
                // 子进程
                // 关闭不需要的文件描述符
                close(pipefd[1]);
                work(pipefd[0]);

                close(pipefd[0]);
                exit(0);
            }
            else
            {
                // 父进程
                // 关闭不需要的文件描述符
                close(pipefd[0]);
                _cm.Insert(pipefd[1],subid);
                

                //close(pipefd[1]);
            }
        }
        return true;
    }



    void Run()
    {
        int taskcode=_tm.code();
        auto& c=_cm.Select();

        std::cout<<"选了一个子进程"<<c.GetName()<<std::endl;
        c.Send(taskcode);
        std::cout<<"发送的一个任务码"<<taskcode<<std::endl;

    }


    void Destory()
    {
        _cm.CloseChannel();
        _cm.StopChannel();
    }
};

#endif